/*
 *  Copyright (C) 2010 Glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.samples;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
import org.balisunrise.annotation.ColumnDefinition;
import org.balisunrise.annotation.CriteriaDefinition;
import org.balisunrise.annotation.FieldDefinition;
import org.balisunrise.annotation.FieldEmbedded;
import org.balisunrise.annotation.FilterCriteria;
import org.balisunrise.annotation.FilterType;
import org.balisunrise.annotation.GridColumn;
import org.balisunrise.annotation.PanelField;
import org.hibernate.annotations.Type;


/**
 *
 * @author Glauco
 */
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "pesType")
public class Pessoa implements Serializable {

    // <editor-fold defaultstate="collapsed" desc="ChangeSupport">
    @Transient
    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
    public static final String PROP_ID = "id";
    public static final String PROP_NOME = "nome";
    public static final String PROP_TIPOPESSOA = "tipoPessoa";
    public static final String PROP_CADASTRONACIONAL = "cadastroNacional";
    public static final String PROP_RGIE = "rgie";
    public static final String PROP_ENDERECO = "endereco";
    public static final String PROP_APELIDO = "apelido";
    public static final String PROP_CELULAR = "celular";
    public static final String PROP_FAX = "fax";
    public static final String PROP_DATACADASTRO = "dataCadastro";
    public static final String PROP_EMAIL = "email";
    public static final String PROP_EMAILNFE = "emailNFe";
    public static final String PROP_ENDERECOS = "enderecos";
    public static final String PROP_OBSERVACOES = "observacoes";
    public static final String PROP_SIMPLESNACIONAL = "simplesNacional";
    public static final String PROP_SUFRAMA = "suframa";
    public static final String PROP_DATAALTERACAO = "dataAlteracao";
    // </editor-fold>


    public Pessoa() {
        endereco = new Endereco();
        enderecos = new ArrayList<EnderecoAdicional>();
        tipoPessoa = TipoPessoa.FISICA;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Basic
    //@Enumerated(EnumType.STRING)
    //@Column(length = 8, columnDefinition = "char(8)")
    //@Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    // </editor-fold>
    private TipoPessoa tipoPessoa;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 60, columnDefinition = "char(60)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = "def", label = "Nome"),
        @FieldDefinition(alias = "jur", label = "Razão Social")})
    @FilterCriteria(definitions = {
        @CriteriaDefinition(alias = "def", label = "Nome", filterType = FilterType.ILIKE),
        @CriteriaDefinition(alias = "jur", label = "Razão Social", filterType = FilterType.ILIKE)})
    @GridColumn(definitions = {
        @ColumnDefinition(alias = "def", name = "Nome", width = 250),
        @ColumnDefinition(alias = "jur", name = "Razão Social", width = 250)})
    // </editor-fold>
    private String nome;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 60, columnDefinition = "char(60)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = "def", label = "Apelido"),
        @FieldDefinition(alias = "jur", label = "Nome Fantasia")})
    // </editor-fold>
    private String apelido;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 18, columnDefinition = "char(18)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = "def", label = "CPF"),
        @FieldDefinition(alias = "jur", label = "CNPJ")})
    // </editor-fold>
    private String cadastroNacional;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 18, columnDefinition = "char(18)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = "def", label = "R.G.", jumpNextRow = false),
        @FieldDefinition(alias = "jur", label = "I.E.", jumpNextRow = false)})
    // </editor-fold>
    private String rgie;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Basic
    @PanelField(embedded =
    @FieldEmbedded(alias = {"def","jur"}, panel = "def"))
    // </editor-fold>
    private Endereco endereco;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 18, columnDefinition = "char(18)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = {"def","jur"}, label = "Celular")})
    // </editor-fold>
    private String celular;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 18, columnDefinition = "char(18)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = {"def","jur"}, label = "Fax", jumpNextRow = false)})
    // </editor-fold>
    private String fax;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Temporal(TemporalType.DATE)
    @PanelField(definitions = {
        @FieldDefinition(alias = {"def","jur"}, label = "Data de Cadastro")})
    // </editor-fold>
    private Date dataCadastro;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 60, columnDefinition = "char(60)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = {"def","jur"}, label = "E-Mail")})
    // </editor-fold>
    private String email;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 60, columnDefinition = "char(60)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    @PanelField(definitions = {
        @FieldDefinition(alias = {"def","jur"}, label = "E-Mail NFe")})
    // </editor-fold>
    private String emailNFe;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @OneToMany(mappedBy = "pessoa", cascade = CascadeType.ALL, orphanRemoval = true)
    // </editor-fold>
    private List<EnderecoAdicional> enderecos;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 2000)
    // </editor-fold>
    private String observacoes;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Basic
    // </editor-fold>
    private Boolean simplesNacional;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Column(length = 9, columnDefinition = "char(9)")
    @Type(type = "org.balisunrise.dao.hibernate.TrimmedString")
    // </editor-fold>
    private String suframa;

    // <editor-fold defaultstate="collapsed" desc="annotations">
    @Temporal(TemporalType.DATE)
    // </editor-fold>
    private Date dataAlteracao;

    // <editor-fold defaultstate="collapsed" desc="Sets & Gets">
    public Date getDataAlteracao() {
        return dataAlteracao;
    }

    public void setDataAlteracao(Date dataAlteracao) {
        Date oldDataAlteracao = this.dataAlteracao;
        this.dataAlteracao = dataAlteracao;
        propertyChangeSupport.firePropertyChange(
                PROP_DATAALTERACAO, oldDataAlteracao, dataAlteracao);
    }

    public String getSuframa() {
        return suframa;
    }

    public void setSuframa(String suframa) {
        String oldSuframa = this.suframa;
        this.suframa = suframa;
        propertyChangeSupport.firePropertyChange(
                PROP_SUFRAMA, oldSuframa, suframa);
    }

    public Boolean getSimplesNacional() {
        return simplesNacional;
    }

    public void setSimplesNacional(Boolean simplesNacional) {
        Boolean oldSimplesNacional = this.simplesNacional;
        this.simplesNacional = simplesNacional;
        propertyChangeSupport.firePropertyChange(
                PROP_SIMPLESNACIONAL, oldSimplesNacional, simplesNacional);
    }

    public String getObservacoes() {
        return observacoes;
    }

    public void setObservacoes(String observacoes) {
        String oldObservacoes = this.observacoes;
        this.observacoes = observacoes;
        propertyChangeSupport.firePropertyChange(
                PROP_OBSERVACOES, oldObservacoes, observacoes);
    }

    public List<EnderecoAdicional> getEnderecos() {
        return enderecos;
    }

    public void setEnderecos(List<EnderecoAdicional> enderecos) {
        List<EnderecoAdicional> oldEnderecos = this.enderecos;
        this.enderecos = enderecos;
        propertyChangeSupport.firePropertyChange(
                PROP_ENDERECOS, oldEnderecos, enderecos);
    }

    public String getEmailNFe() {
        return emailNFe;
    }

    public void setEmailNFe(String emailNFe) {
        String oldEmailNFe = this.emailNFe;
        this.emailNFe = emailNFe;
        propertyChangeSupport.firePropertyChange(
                PROP_EMAILNFE, oldEmailNFe, emailNFe);
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        String oldEmail = this.email;
        this.email = email;
        propertyChangeSupport.firePropertyChange(PROP_EMAIL, oldEmail, email);
    }

    public Date getDataCadastro() {
        return dataCadastro;
    }

    public void setDataCadastro(Date dataCadastro) {
        Date oldDataCadastro = this.dataCadastro;
        this.dataCadastro = dataCadastro;
        propertyChangeSupport.firePropertyChange(
                PROP_DATACADASTRO, oldDataCadastro, dataCadastro);
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        String oldFax = this.fax;
        this.fax = fax;
        propertyChangeSupport.firePropertyChange(PROP_FAX, oldFax, fax);
    }

    public String getCelular() {
        return celular;
    }

    public void setCelular(String celular) {
        String oldCelular = this.celular;
        this.celular = celular;
        propertyChangeSupport.firePropertyChange(
                PROP_CELULAR, oldCelular, celular);
    }

    public String getApelido() {
        return apelido;
    }

    public void setApelido(String apelido) {
        String oldApelido = this.apelido;
        this.apelido = apelido;
        propertyChangeSupport.firePropertyChange(
                PROP_APELIDO, oldApelido, apelido);
    }

    @Enumerated(EnumType.STRING)
    public TipoPessoa getTipoPessoa() {
        return tipoPessoa;
    }

    public void setTipoPessoa(TipoPessoa tipoPessoa) {

        if(tipoPessoa == null)
            throw new RuntimeException("Tipo de Pessoa deve ser informado!");

        TipoPessoa oldTipoPessoa = this.tipoPessoa;
        this.tipoPessoa = tipoPessoa;
        propertyChangeSupport.firePropertyChange(
                PROP_TIPOPESSOA, oldTipoPessoa, tipoPessoa);
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {

        if(nome == null || nome.length() == 0)
            throw new RuntimeException("Nome deve ser informado!");

        String oldNome = this.nome;
        this.nome = nome;
        propertyChangeSupport.firePropertyChange(PROP_NOME, oldNome, nome);
    }

    public Endereco getEndereco() {
        if(endereco == null)
            endereco = new Endereco();
        return endereco;
    }

    public void setEndereco(Endereco endereco) {
        Endereco oldEndereco = this.endereco;
        this.endereco = endereco;
        propertyChangeSupport.firePropertyChange(
                PROP_ENDERECO, oldEndereco, endereco);
    }

    public String getRgie() {
        return rgie;
    }

    public void setRgie(String rgie) {
        String oldRgie = this.rgie;
        this.rgie = rgie;
        propertyChangeSupport.firePropertyChange(PROP_RGIE, oldRgie, rgie);
    }

    public String getCadastroNacional() {
        return cadastroNacional;
    }

    public void setCadastroNacional(String cadastroNacional) {

        if(cadastroNacional == null || cadastroNacional.length() == 0){
            String msg;
            switch (tipoPessoa) {
                case FISICA:
                    msg = "CPF deve ser informado!";
                    break;
                case JURIDICA:
                    msg = "CNPJ deve ser informado!";
                    break;
                default:
                    msg = "Tipo de Pessoa deve ser informado!";
            }
            throw new RuntimeException(msg);
        }

        String oldCadastroNacional = this.cadastroNacional;
        this.cadastroNacional = cadastroNacional;
        propertyChangeSupport.firePropertyChange(
                PROP_CADASTRONACIONAL, oldCadastroNacional, cadastroNacional);
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        Long oldId = this.id;
        this.id = id;
        propertyChangeSupport.firePropertyChange(PROP_ID, oldId, id);
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Pessoa)) {
            return false;
        }
        Pessoa other = (Pessoa) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "org.balisunrise.samples.Pessoa[id=" + id + "]";
    }
    // </editor-fold>

}
